#include "iBe.h"

Cmd::Cmd(const UINT16 &_cmd): cmd(_cmd)
{}

Cmd::~Cmd()
{}

void Cmd::write(std::ostream &_os) const
{
  write(_os, cmd);
  internalWrite(_os);
}

void Cmd::write(std::ostream &_os, const StringHash &_name) const
{
  _os.write((char*) &_name.hash[0], sizeof(_name.hash[0]));
  _os.write((char*) &_name.hash[1], sizeof(_name.hash[1]));
}

void Cmd::write(std::ostream &_os, const float &_value) const
{
  _os.write((char*) &_value, sizeof(_value));
}

void Cmd::write(std::ostream &_os, const UINT16 &_cmd) const
{
  _os.write((char*) &_cmd, sizeof(_cmd));
}

CreateObject::CreateObject(const StringHash &_name,
			   const StringHash &_model) : 
  Cmd(VM::CMD_CREATE), name(_name), model(_model)
{}

void CreateObject::internalWrite(std::ostream &_os) const
{
  write(_os, name);
  write(_os, model);
}

void CreateObject::printOut() const
{
  std::cout << "CreateObject" << std::endl;
}

CreateObject::~CreateObject()
{}

End::End():Cmd(VM::CMD_END)
{}

End::~End()
{}

void End::internalWrite(std::ostream &_os) const 
{
}

void End::printOut() const
{
  std::cout << "End" << std::endl;
}

SetValue::SetValue(const StringHash &_name, const float &_value) :
  Cmd(VM::CMD_SETVALUE), name(_name), value(_value)
{}

SetValue::~SetValue()
{}

void SetValue::internalWrite(std::ostream &_os) const 
{
  write(_os, name);
  write(_os, value);
}

void SetValue::printOut() const
{
  std::cout << "Set value " << value << std::endl;
}

CmdList::CmdList()
{}

CmdList::~CmdList()
{}

void CmdList::addCreateObject( const String &_name, const String &_model )
{
  StringHash nameHash = System::hash( _name );
  StringHash modelHash = System::hash( _model );
  CmdPtr cmd( new CreateObject( nameHash, modelHash ) );
  cmdList.push_back(cmd);
}


void CmdList::addSetValue( const String &_name, const float &_val )
{
  StringHash nameHash = System::hash( _name );
  CmdPtr cmd( new SetValue( nameHash, _val ) );
  cmdList.push_back(cmd);
}

void CmdList::addEnd()
{
  CmdPtr cmd( new End() );
  cmdList.push_back(cmd);
}

void CmdList::write(std::ostream &_os)
{
  ListType::iterator it;
  
  for(it = cmdList.begin(); it != cmdList.end(); ++it)
    {
      std::cout << "-" << std::endl;
      (*it) -> write(_os);
    }
 
}

void CmdList::printOut()
{
  ListType::iterator it;

  for(it = cmdList.begin(); it != cmdList.end(); ++it)
    {
      std::cout << "-" << std::endl;
      (*it) -> printOut();
    }
}

VMPtr VM::inst;

VM::VM()
{}

VM::~VM()
{}

VMPtr VM::instance()
{
  if ( !inst )
    {
      inst.reset( new VM() );
    }
  return inst;
}

int VM::open(const char* const _filename)
{
  ifs.open(_filename, std::ios::binary);

  if (ifs)
    return 0;
  else
    return -1;
}

bool VM::doCreate(const StringHash &_param1, const StringHash &_param2)
{
  if (!_param1 || !_param2)
    return false;
  
  return true;
}

bool VM::doSetValue(const StringHash &_param, const float &_value)
{
  if (!_param)
    return false;

  return true;
}

bool VM::doEnd()
{
  return true;
}

int VM::run()
{
  UINT16 cmd;
  StringHash param1, param2;
  float  value;
  bool done = false;

  if (!ifs)
    {
      return -1;
    }

  while(!ifs.eof() && !done)
    {
      cmd = CMD_ERROR;
      read(ifs, cmd);
      switch (cmd)
	{
	case 0:
	  done = true;
	  break;

	case CMD_CREATE:
	  param1.reset();
	  param2.reset();
	  read(ifs, param1);
	  read(ifs, param2);
	  doCreate(param1, param2);
	  break;

	case CMD_SETVALUE:
	  param1.reset();
	  value = 0;
	  read(ifs, param1);
	  read(ifs, value);
	  doSetValue(param1, value);
	  break;

	case CMD_END:
	  break;

	default:
	  std::cerr << "Unknown cmd (" << cmd << ")" << std::endl;
	  done = true;
	  break;
	}
    }

  return 0;
}

